﻿//StopLossStrategy.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo.Strategies
{
	using StockSharp.BusinessEntities;

	/// <summary>
	/// Стратегия защиты убытка.
	/// </summary>
	public class StopLossStrategy : ProtectiveStrategy
	{
		private decimal? _prevPrice;

		/// <summary>
		/// Создать стратегию <see cref="StopLossStrategy"/>.
		/// </summary>
		/// <param name="trade">Защищаемая позиция.</param>
		/// <param name="protectiveLevel">
		/// Защитный уровень. Если тип <see cref="Unit.Type"/> равен <see cref="UnitTypes.Limit"/>,
		/// то задается конкретная цена. Иначе, указывается величина сдвига от защищаемой сделки <paramref name="trade"/>.
		/// </param>
		public StopLossStrategy(MyTrade trade, Unit protectiveLevel)
			: base(trade, protectiveLevel)
		{
			_activationOffset = this.Param("ActivationOffset", new Unit());
		}

		private readonly StrategyParam<Unit> _activationOffset;

		/// <summary>
		/// Защитный сдвиг от расcчитанной цены стопа <see cref="ActivationPrice"/>, который позволяет активировать защиту до достижения рынком данной цены.
		/// По-умолчанию выключено.
		/// </summary>
		public Unit ActivationOffset
		{
			get { return _activationOffset.Value; }
			set { _activationOffset.Value = value; }
		}

		/// <summary>
		/// Абсолютное значение цены, при достижении которой автивизируется защитная стратегия. Если цена равна 0, то активация не требуется.
		/// </summary>
		public override decimal ActivationPrice
		{
			get
			{
				var isBuy = ProtectiveDirection == OrderDirections.Buy;

				if (_prevPrice == null)
					_prevPrice = BasePrice;

				var bestPrice = BestPrice;

				if (IsTimeOut && (isBuy ? BestPrice < BasePrice : BestPrice > BasePrice))
					return ClosePositionPrice;

				if (IsTrailing)
				{
					// подтягиваем цену в сторону безубытка

					if (isBuy)
					{
						if (_prevPrice < bestPrice)
							_prevPrice = bestPrice;
					}
					else
					{
						if (_prevPrice > bestPrice)
							_prevPrice = bestPrice;
					}
				}

				var activationPrice = (decimal)(isBuy ? (decimal)_prevPrice - ProtectiveLevel : (decimal)_prevPrice + ProtectiveLevel);

				if (isBuy)
				{
					if (bestPrice <= (activationPrice + ActivationOffset))
						return ClosePositionPrice;
				}
				else
				{
					if (bestPrice >= (activationPrice - ActivationOffset))
						return ClosePositionPrice;
				}

				return 0;
			}
		}
	}
}